/**
 * 时间范围滑块选择插件
 * 基于 layui.slider 扩展的时间范围选择插件
 *
 * sliderTime.js License By momo
 * V1.0 2021-04-19
 *
 *
 * 使用说明：
 * 1.sliderTime 基于 layui.slider，所以 slider 的配置都得以保留
 * 2.range 参数强制为 true
 * 3.新增 disabledValue 属性，禁止选择时间范围
 *   例如：[[8:00, 10:00], [14:00, 15:00]]
 * 4.新增 disabledText 属性，禁止选择时间范围被选中后的提示内容，不配置不显示提示
 *   例如：'{start} - {end} 已占用'，支持start和end时间占位符
 * 5.新增 getValue 方法，返回当前选择的时间段（时间格式）
 * 6.新增 isOccupation 方法，返回当前选择的时间段是否包含了禁止选择的时间段
 * 7.新增 numToTime 公用方法，用于将十进制转为时间格式。例如：480 → 08:00
 * 8.新增 timeToNum 公用方法，用于将时间格式转为十进制。例如：24:00 → 1440
 */
layui.define(['slider'], function (exports) {
    "use strict";
    var MOD_NAME = 'sliderTime',
        $ = layui.jquery,
        slider = layui.slider;
    ;

    /**
     * 外部接口
     */
    var SliderTime = {
        config: {}
        /**
         * 核心入口
         */
        , render: function (options) {
            var object = new Class(options);
            return thisSliderTime.call(object);
        }

        /**
         * 数字转时间格式
         */
        , numToTime: function (value) {
            var hours = Math.floor(value / 60);
            var mins = (value - hours * 60);
            return (hours < 10 ? "0" + hours : hours) + ":" + (mins < 10 ? "0" + mins : mins);
        }

        /**
         * 时间转数字
         */
        , timeToNum: function (value) {
            var time = value.split(":");
            return time[0] * 60 + parseInt(time[1]);
        }
    };

    /**
     * 构造器
     */
    var Class = function (options) {
        var that = this;
        that.config = $.extend({}, SliderTime.config, options);
        that.render();
    };

    /**
     * 操作当前实例
     */
    var thisSliderTime = function () {
        var that = this
            , options = that.config;

        return {
            /**
             * 设置时间段
             */
            setValue: function (value, index) {
                if (index !== 1) {
                    index = 0;
                }
                value = SliderTime.timeToNum(value);
                var start, end, width,
                    $wrap = $(options.elem).find('.layui-slider-wrap'),
                    val = [$wrap.eq(0).data("value"), $wrap.eq(1).data("value")];
                if (value === val[0] || value === val[1]) {
                    // 设置值等于当前最小或最大值，不移动
                    return;
                } else if (value > val[1]) {
                    // 设置值大于当前最大值，移动后面圆点
                    val[1] > val[0] ? index = 1 : index = 0;
                    val[index] = value;
                } else if (value < val[0]) {
                    // 设置值小于当前最小值，移动前面圆点
                    val[0] < val[1] ? index = 0 : index = 1;
                    val[index] = value;
                } else {
                    // 设置值间与中间，则按照index移动
                    index === 0 ? val[0] = value : val[1] = value;
                }
                $wrap.eq(index).data("value", value);

                start = (val[0] - options.min) / (options.max - options.min) * 100;
                end = (val[1] - options.min) / (options.max - options.min) * 100;
                // 设置圆点位置
                if ("vertical" === options.type) {
                    $(options.elem).find('.layui-slider-wrap').eq(index).css("bottom", (index === 0 ? start : end) + '%');
                } else {
                    $(options.elem).find('.layui-slider-wrap').eq(index).css("left", (index === 0 ? start : end) + '%');
                }
                // 设置滑动位置
                width = Math.abs(end - start);
                if ("vertical" === options.type) {
                    $(options.elem).find('.layui-slider-bar').css({
                        "height": width + '%',
                        "bottom": (start < end ? start : end) + '%'
                    });
                } else {
                    $(options.elem).find('.layui-slider-bar').css({
                        "width": width + '%',
                        "left": (start < end ? start : end) + '%'
                    });
                }
                return;
                // return that.slider.setValue(SliderTime.timeToNum(value), index)
            }

            /**
             * 获取选中的时间段
             */
            , getValue: function () {
                var $wrap = $(options.elem).find('.layui-slider-wrap');
                var value = [$wrap.eq(0).data("value"), $wrap.eq(1).data("value")];
                //如果前面的圆点超过了后面的圆点值，则调换顺序
                if (value[0] > value[1]) {
                    value.reverse();
                }
                return [SliderTime.numToTime(value[0]), SliderTime.numToTime(value[1])];
            }
            /**
             * 选择的时间段是否包含被禁止选择的时间段
             * 包含：返回禁止选择的时间段
             * 不包含：false
             */
            , isOccupation: function () {
                if (options.disabledValue) {
                    var $wrap = $(options.elem).find('.layui-slider-wrap');
                    var value = [$wrap.eq(0).data("value"), $wrap.eq(1).data("value")];
                    //如果前面的圆点超过了后面的圆点值，则调换顺序
                    if (value[0] > value[1]) {
                        value.reverse();
                    }
                    for (var i in options.disabledValue) {
                        var date = options.disabledValue[i];
                        var min = SliderTime.timeToNum(date[0]);
                        var max = SliderTime.timeToNum(date[1]);
                        if (value[0] > min && value[0] < max
                            || value[1] > min && value[1] < max
                            || value[0] <= min && value[1] >= max) {
                            return date;
                        } else {
                            that.closeTips(options.elem);
                        }
                    }
                    return false;
                } else {
                    return false;
                }
            }
            , config: options
        }
    };

    /**
     * 滑块渲染
     * @param options
     */
    Class.prototype.render = function () {
        var that = this
            , options = that.config;
        // 是否显示时刻，默认是
        options.showstep = options.showstep == false ? false : true;
        // 开启滑块的范围拖拽
        options.range = true;
        // 最小值，最小为0=0:00
        options.min = options.min == undefined || SliderTime.timeToNum(options.min) < 0 ? 0 : SliderTime.timeToNum(options.min);
        // 最大值，最大为1440=24*60=24:00
        options.max = options.max == undefined || SliderTime.timeToNum(options.max) > 1440 ? 1440 : SliderTime.timeToNum(options.max);
        //间隔值不能大于 max
        options.step = options.step > options.max ? options.max : options.step;
        // 初始值
        options.value = typeof (options.value) == 'object' ? options.value : [SliderTime.numToTime(options.min), SliderTime.numToTime(options.min)];
        options.value[0] = SliderTime.timeToNum(options.value[0]);
        options.value[1] = SliderTime.timeToNum(options.value[1]);

        // 初始化
        that.slider = slider.render({
            elem: options.elem
            , type: options.type
            , height: options.height
            , theme: options.theme
            , range: options.range
            , showstep: options.showstep
            , min: options.min
            , max: options.max
            , step: options.step
            , value: options.value
            , disabled: options.disabled
            , setTips: function (value) {
                value = SliderTime.numToTime(value);
                if (options.setTips) {
                    return options.setTips(value);
                } else {
                    return value;
                }
            }
            , change: function (value) {
                if (options.disabledValue && options.disabledText) {
                    // 当滑动到禁用时间范围时，自动提醒
                    for (var i in options.disabledValue) {
                        var date = options.disabledValue[i];
                        var min = SliderTime.timeToNum(date[0]);
                        var max = SliderTime.timeToNum(date[1]);
                        if (value[0] > min && value[0] < max
                            || value[1] > min && value[1] < max
                            || value[0] <= min && value[1] >= max) {
                            var disabledText = options.disabledText.replace('{start}', date[0]).replace('{end}', date[1])
                            that.showTips(options, disabledText)
                            break;
                        } else {
                            that.closeTips(options.elem);
                        }
                    }
                }
                if (options.change) {
                    options.change(value);
                }
            }
        });

        // 扩展元素
        $(options.elem).find('.layui-slider')
        // 开始结尾刻度时间
            .append('<div class="step-start-num">' + SliderTime.numToTime(options.min) + '</div>')
            .append('<div class="step-end-num">' + SliderTime.numToTime(options.max) + '</div>')
            // 警告提示Tips
            .append('<div class="slider-danger-tips"></div>');
        if (options.showstep) {
            // 开始结尾刻度标识
            $(options.elem).find('.layui-slider')
                .append('<div class="step-start-wrap"></div>')
                .append('<div class="step-end-wrap"></div>');
        }


        // 定义整点和半点时刻标识
        var $steps = $(options.elem).find('.layui-slider .layui-slider-step');
        for (var i = 0, num = options.min; num <= options.max && i < $steps.length - 1; i++, num += options.step) {
            if (that.numToMins(num) == 0 && i > 0) {
                $steps.eq(i - 1).addClass('step-hour');

            } else if (that.numToMins(num) == 30) {
                $steps.eq(i - 1).addClass('step-half-hour');
            }
        }

        // 初始化选中禁止选择时间范围
        if (options.disabledValue) {
            options.disabledValue.forEach(function (date) {
                var dateNum = [SliderTime.timeToNum(date[0]), SliderTime.timeToNum(date[1])];

                var start = (dateNum[0] - options.min) / (options.max - options.min) * 100,
                    end = (dateNum[1] - options.min) / (options.max - options.min) * 100,
                    width = end - start;
                var selectedSlider = '<div class="layui-slider-bar-selected layui-disabled" style=" ' + ("vertical" === options.type ? "height" : "width") + ':' + width + '%; ' + ("vertical" === options.type ? "bottom" : "left") + ':' + start + '% ;"></div>';
                $(options.elem).find('.layui-slider-bar').after(selectedSlider);
            });
        }

        // 主题设置
        if (options.theme) {
            $(options.elem).find('.step-hour,.step-half-hour,.step-start-wrap,.step-end-wrap,.layui-slider-step').css("background", options.theme);
        }
    };

    /**
     * 数字转分钟
     */
    Class.prototype.numToMins = function (value) {
        var hours = Math.floor(value / 60);
        var mins = (value - hours * 60);
        return mins;
    };

    /**
     * 显示警告信息
     */
    Class.prototype.showTips = function (options, text) {
        if ("vertical" === options.type) {
            $(options.elem).find('.slider-danger-tips').css({
                "display": "block",
                "bottom": $(options.elem).find('.layui-slider-tips')[0].style.bottom
            }).text(text);
        } else {
            $(options.elem).find('.slider-danger-tips').css({
                "display": "block",
                "left": $(options.elem).find('.layui-slider-tips')[0].style.left
            }).text(text);
        }

    };

    /**
     * 关闭警告信息
     */
    Class.prototype.closeTips = function (elem) {
        $(elem).find('.slider-danger-tips').css({
            "display": "none"
        }).text('');
    };

    // 加载css
    layui.link(layui.cache.base + 'sliderTime/sliderTime.css');
    exports(MOD_NAME, SliderTime);
});